package com.hqy.gateway.filter;

import com.hqy.gateway.config.WhiteListPathsConfig;
import com.hqy.gateway.util.IpUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
//@Order(1)
public class GmallGatewayFilter implements GlobalFilter {

    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_PREFIX = "bearer ";
    private static final String TOKEN = "token";


    @Autowired
    private WhiteListPathsConfig whiteListPathsConfig;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String path = request.getURI().getPath();

        // 从配置获取白名单路径
        List<String> whiteList = whiteListPathsConfig.getWhiteListPaths();

        // 检查是否为白名单路径
        if (isWhiteListPath(path, whiteList)) {
            return chain.filter(exchange); // 白名单路径直接放行
        }

        //从查询参数中获取token
        String token = request.getQueryParams().getFirst(TOKEN);
        if (StringUtils.isEmpty(token)){
            //从请求头中获取token
            token = request.getHeaders().getFirst(TOKEN);
            if (StringUtils.isEmpty(token)){
                //从cookie中获取token todo 稍后弄清楚，app手机端为什么不用cookie，以及我们怎么解决这个问题呢
                MultiValueMap<String, HttpCookie> cookies = request.getCookies();
                HttpCookie token1 = cookies.getFirst(TOKEN);
                token = token1.getValue();
            }
        }

        if (StringUtils.isEmpty(token)){
            //引导到登录页面 todo
            response.setStatusCode(HttpStatus.NETWORK_AUTHENTICATION_REQUIRED);
            return response.setComplete();
        }

        //token 防盗
        String gatwayIpAddress = IpUtil.getGatwayIpAddress(request);
        String redisToken = stringRedisTemplate.opsForValue().get(gatwayIpAddress);

        if(StringUtils.isEmpty(redisToken) || !token.equals(redisToken)){
            //引导到登录页面 todo
            response.setStatusCode(HttpStatus.NETWORK_AUTHENTICATION_REQUIRED);
            return response.setComplete();
        }

        //处理组装token
        request.mutate().header(AUTHORIZATION_HEADER, BEARER_PREFIX + token);

        return chain.filter(exchange);
    }

    /**
     * 检查是否为白名单路径
     * @param path
     * @param whiteList
     * @return
     */
    private boolean isWhiteListPath(String path, List<String> whiteList) {
        if (CollectionUtils.isEmpty(whiteList)) {
            return false;
        }
        return whiteList.stream().anyMatch(pattern ->
                path.startsWith(pattern) || path.matches(pattern)
        );
    }
}
